var ctx = canvas.getContext('2d'),
  difficulty = 1, //每行随机两个数为空, 2 3 4 5
  width = 0,
  padding = { //上下左右四个间距
    top: 60,
    bottom: 0,
    left: 10,
    right: 20
  },
  rows = 0,
  cols = 0,
  background = '',
  cell = {
    id: '',
    bg: '#cccccc', //正常背景色
    bg_wrong: '#f23622', //錯誤提示的背景色
    bg_now: '#FFD700', //当前点击的元素
    color: '#5f7287', //正常字體顔色
    color_guess: '#4a86e8', //選擇后的字體顔色
    num: -1, //初始化時的數字
    guess: -1, //用戶選擇的數字
    right: false, //是否猜正確，默認false,
    repeat: false, //repeat or not, default is false
    x0: -1, //當前cell的起始x坐標
    x: -1, //當前cell的終止x坐標  
    y0: -1, //當前cell的起始y坐標
    y: -1, //當前cell的終止y坐標（這幾個坐標值用於判斷用戶點擊的是哪個cell並作相應處理）
    show_num: true, //決定是否隱藏當前num
    show_num_init: true
  }

let {
  screenWidth,
  screenHeight,
} = wx.getSystemInfoSync()


/**
 * 产生随机整数，包含下限值，包括上限值
 * @param {Number} lower 下限
 * @param {Number} upper 上限
 * @return {Number} 返回在下限到上限之间的一个随机整数
 */
function random(lower, upper) {
  return Math.floor(Math.random() * (upper - lower + 1)) + lower;
}

function find_id(id, pair) {
  return id == pair
}

//删除数组中指定元素
Array.prototype.remove = function(val) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == val) {
      this.splice(i, 1);
      i--;
    }
  }
};

var S = Sudoku = {
  /**************************数据存储******************************/
  editable: [], //所有可编辑项
  now: null, //当前点击的项目,
  same: [],
  keyboard: [],
  numTable: [], //答案用表   9X9
  gameTable: [], //游戏用表
  editable: [], //游戏时可编辑表
  editIndex: '', //现在正在编辑Index
  selectTab: '', //数字选择表
  elem: '', //DIV生成字符串	9X9
  answerStr: '', //答案生成字符串	
  num: [1, 2, 3, 4, 5, 6, 7, 8, 9], //1-9数组
  tab: [ //9块3X3
    [
      [],
      [],
      []
    ],
    [
      [],
      [],
      []
    ],
    [
      [],
      [],
      []
    ]
  ],
  row: [
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    []
  ], //9行
  col: [
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    []
  ], //9列
  level: [20, 40, 60, 80], //4个等级
  interval: null, //计时器
  time: 0, //计时器，单位秒
  /****************
   * 0.数据初始化
   *****************/
  clear: function() {
    S.numTable = [];
    S.elem = "";
    S.tab = [
      [
        [],
        [],
        []
      ],
      [
        [],
        [],
        []
      ],
      [
        [],
        [],
        []
      ]
    ];
    S.row = [
      [],
      [],
      [],
      [],
      [],
      [],
      [],
      [],
      []
    ];
    S.col = [
      [],
      [],
      [],
      [],
      [],
      [],
      [],
      [],
      []
    ];
    S.time = 0;
    S.answerStr = '';
    S.selectTab = '';

  },
  /****************
   * 1.生成数独
   *****************/
  getNewTable: function() {

    var insertNum
    S.num.sort(function() {
      return Math.random() > 0.5 ? -1 : 1;
    });

    //生成第一行
    for (var i = 0; i < 9; i++) {
      S.numTable.push(S.num[i]);
      var c = JSON.parse(JSON.stringify(cell))
      c.num = S.num[i]
      S.col[i].push(c);
      S.tab[0][parseInt((i % 9) / 3)].push(S.num[i]);
    }

    //生成后八行
    for (var i = 1; i < 9; i++) {
      for (var j = 0; j < 9; j++) {
        var flag = true; //flag 记录新生成数是否正确
        var answer = [1, 2, 3, 4, 5, 6, 7, 8, 9]; //未开始验证时1-9均可
        //在可选答案中除去列相同元素
        for (var k = 0; k < S.col[j].length; k++) {
          answer[S.col[j][k].num - 1] = 0;
        }
        //在可选答案中除去行相同元素
        for (var k = 0; k < S.row[i].length; k++) {
          answer[S.row[i][k] - 1] = 0;
        }
        //在可选答案中除去3x3相同元素
        for (var k = 0; k < S.tab[parseInt(i / 3)][parseInt(j / 3)].length; k++) {
          answer[S.tab[parseInt(i / 3)][parseInt(j / 3)][k] - 1] = 0;
        }
        //得到可行数组
        answer.remove(0);
        //若得到可行数组长度为0 则此处无解 生成数独失败
        if (answer.length == 0) {
          S.answerInit();
          return false;
        }

        //可行数组中随机产生一个可行解
        insertNum = answer[Math.floor(Math.random() * answer.length)]
        var c1 = JSON.parse(JSON.stringify(cell))
        c1.num = insertNum

        //将这个数存入验证数组				
        S.numTable.push(insertNum);
        S.row[i].push(insertNum);
        S.col[j].push(c1);
        S.tab[parseInt(i / 3)][parseInt(j / 3)].push(insertNum);
        //调试
        //console.log(i+'横排:'+S.row[i]+'\n'+j+'竖排：'+S.col[j] +'\n方块：'+S.tab[parseInt(i/3)][parseInt(j/3)]+'\n数独：'+S.numTable +'\n此时可选数列:'+answer)
      }
    }

    return true;
  },

  /********************************************
   * 2.参考答案界面初始化(生成完全的数独，无空格)
   *********************************************/
  answerInit: function() {
    S.clear();
    if (S.getNewTable()) {

      //var one = []

      //填充单元格颜色
      for (var i = 0; i < S.col.length; i++) {
        var rd = []

        for (var a = 0; a < difficulty; a++) //根据难度等级
          rd.push(random(1, 9))

        for (var j = 0; j < rd.length; j++) {
          S.col[i][rd[j] - 1].show_num = false
          S.col[i][rd[j] - 1].show_num_init = false
          S.editable.push(S.col[i][rd[j] - 1])
        }

        //one.push(S.col[i][0])
      }

      //S.row[0] = one //補充S.row第一列

      //上色宮#aaaaaa
      for (var i = 0; i < 81; i++) {
        //开始向数独数组内存数number对象
        rows = parseInt(i / 9) + 1;
        cols = parseInt(i % 9) + 1;
        //开始创建界面
        if (!(((rows <= 3 || rows >= 7) && (cols <= 3 || cols >= 7)) || ((rows >= 4 && rows <= 6) && (cols >= 4 && cols <= 6))))
          S.col[rows - 1][cols - 1].bg = '#aaaaaa'

      }
    }
  },
  /********************************************
   * 3.游戏界面初始化(传入LV为等级)
   *********************************************/
  gameInit: function() {},
  /********************************************
   * 4.游戏界面刷新
   *********************************************/
  gameBoard: function() {},
  /********************************************
   * 5.事件绑定
   *********************************************/
  gameEvent: function() {},
  /********************************************
   * 6.游戏中检查
   *********************************************/
  gameCheck: function() {},
  /********************************************
   * 7.游戏计时
   *********************************************/
  showTime: function() {},
  /********************************************
   * 8.游戏失败，显示答案
   *********************************************/
  gameOver: function() {
    if (S.elem == '') {
      alert('游戏未开始');
    } else {
      clearInterval(S.interval);
      $('gameBoard').innerHTML = S.answerStr;
    }
  },
  /********************************************
   * 9.游戏初始化
   *********************************************/
  init: function() {
    S.answerInit();
    //S.gameInit();
    //S.gameEvent();
  },
}



export default class Sudoku {
  constructor() {
    this.restart()
  }

  restart() {

    //清空画布，布置背景
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(0, 0, screenWidth, screenHeight);

    canvas.removeEventListener(
      'touchstart',
      this.touchHandler
    )

    this.touchHandler = this.touchEventHandler.bind(this)
    canvas.addEventListener('touchstart', this.touchHandler)

    var s = S;
    s.init()

    this.table()

    console.error(S)
  }

  table() {

    width = (canvas.width - padding.left - padding.right) / 9;
    var img = new Image();

    var padding_left = 0,
      padding_top = 0;

    var repeat = []
    //绘制格子    
    for (var i = 0; i < S.col.length; i++) {

      if (i == 0)
        padding_top += padding.top

      for (var j = 0; j < S.col[i].length; j++) {

        //为每个格子填充一个id
        S.col[i][j].id = i + '-' + j

        var item = S.col[i][j]
        var x = padding_left + padding.left + width / 2 - 4,
          y = padding_top + width / 2 + 3
        var x0 = padding_left + padding.left,
          y0 = padding_top

        ctx.font = "Normal Semi 16px"

        if (item.repeat)
          ctx.fillStyle = item.bg_wrong
        else {
          if (S.now && (item.id == S.now.id))
            ctx.fillStyle = item.bg_now
          else
            ctx.fillStyle = item.bg
        }

        //绘制实心矩形 距离左边距，距离上边距，矩形长度，矩形高度
        ctx.fillRect(padding_left + padding.left, padding_top, width, width);

        if (item.show_num)
          if (item.guess == -1) {
            ctx.fillStyle = item.color
            ctx.fillText(item.num, x, y)
          } else {
            ctx.fillStyle = item.color_guess
            ctx.fillText(item.guess, x, y)
          }

        S.col[i][j].x0 = x0;
        S.col[i][j].y0 = y0;

        S.col[i][j].x = x0 + width;
        S.col[i][j].y = y0 + width;

        padding_left += width + 1;
      }

      padding_left = 0
      padding_top += width + 1
    }
  }

  touchEventHandler(e) {
    e.preventDefault()
    let x = e.touches[0].clientX
    let y = e.touches[0].clientY

    this.x = x;
    this.y = y;
    var that = this;
    var c = null,
      k = null;
    for (var i = 0; i < S.col.length; i++) {
      for (var j = 0; j < S.col[i].length; j++) {
        var it = S.col[i][j]
        if (that.x >= it.x0 && that.x <= it.x && that.y >= it.y0 && that.y <= it.y) {
          if (!it.show_num || it.guess != -1) {
            c = it;
            break
          }
        }
      }

      if (c)
        break

    }

    if (c) { //点击的对象是9*9的格子之一
      if (S.now) { //清空之间的选择

        var now = S.now
        ctx.fillStyle = now.bg
        //绘制实心矩形 距离左边距，距离上边距，矩形长度，矩形高度
        ctx.fillRect(now.x0, now.y0, width, width)
        ctx.fillStyle = now.color

        if (now.guess != -1) {
          ctx.fillStyle = now.color_guess
          ctx.fillText(now.guess, now.x0 + 16, now.y0 + width / 2 + 3)
        }
      }

      S.now = c

      ctx.fillStyle = c.bg_now
      //绘制实心矩形 距离左边距，距离上边距，矩形长度，矩形高度
      ctx.fillRect(c.x0, c.y0, width, width);

      ctx.fillStyle = c.color
      //绘制选择区
      var last = S.col[S.col.length - 1][2]

      //重绘选择区(清零)，键盘区
      ctx.fillStyle = '#ffffff'
      ctx.fillRect(last.x, last.y + 40, 3 * width + 3, 3 * width + 3)

      setTimeout(() => {
        var pd_left = last.x,
          pd_top = last.y

        S.keyboard = []
        for (var i = 0; i < S.col.length; i++) {

          var k = JSON.parse(JSON.stringify(cell))
          k.x0 = pd_left;
          k.y0 = pd_top + 40;
          k.x = k.x0 + width
          k.y = k.y0 + width
          k.num = i + 1
          k.bg = '#0099CC'
          k.color = '#ffffff'

          S.keyboard.push(k)

          ctx.fillStyle = k.bg
          ctx.fillRect(pd_left, pd_top + 40, width, width)

          ctx.fillStyle = k.color
          ctx.fillText(i + 1, pd_left + 16, pd_top + 64)

          if ((i + 1) % 3 == 0) {
            pd_left = last.x
            pd_top += width + 1
          } else
            pd_left += width + 1
        }
      }, 100);

    } else {
      //判断是否点击了9字键盘区
      for (var i = 0; i < S.keyboard.length; i++) {
        var it = S.keyboard[i]
        if (that.x >= it.x0 && that.x <= it.x && that.y >= it.y0 && that.y <= it.y) {
          k = it;
          break
        }

        if (k)
          break
      }

      if (k) { //点击的是键盘区

        //判断重复
        var coords = S.now.id.split('-')
        var xx = coords[0],
          yy = coords[1]

        console.warn(k.num)
        console.warn(S.col[xx][yy].num)

        that.xx = xx
        that.yy = yy
        if (k.num == S.col[xx][yy].num) {
          for (var i = 0; i < S.editable.length; i++) {
            var item = S.editable[i].id.split('-')
            var a = item[0],
              b = item[1]

            if (a == xx && b == yy)
              S.editable[i].right = true
          }
        }


        S.col[xx][yy].right = (k.num == S.col[xx][yy].num)
        S.col[xx][yy].guess = k.num
        S.col[xx][yy].show_num = true

        var all_clear = true
        S.editable.map((e) => {
          if (!e.right)
            all_clear = false
        })

        if (all_clear)
          console.error("ALL CLEAR----------------------")

        //绘制选择区
        var last = S.col[S.col.length - 1][2]

        //重绘选择区(清零)，键盘区
        ctx.fillStyle = '#ffffff'
        ctx.fillRect(last.x, last.y + 40, 3 * width + 3, 3 * width + 3)

        //获取重复项目并着色提醒
        var coords = S.now.id.split('-')
        var xx = coords[0],
          yy = coords[1]

        S.col[xx][yy].guess = k.num
        S.col[xx][yy].show_num = true

        var same = [];
        for (var i = 0; i < S.col[xx].length; i++) {
          var item = S.col[xx][i]
          if (item.show_num) {
            if (item.num == S.now.guess || item.guess == S.now.guess) {
              same.push(item)
            }
          }

          var item2 = S.col[i][yy]
          if (item.show_num) {
            if (item2.num == S.now.guess || item2.guess == S.now.guess)
              same.push(item2)
          }
        }

        //去重
        var obj = {};
        same = same.reduce(function(item, next) {
          obj[next.id] ? '' : obj[next.id] = true && item.push(next);
          return item;

        }, []);


        ///TODO: 重複提示

        this.table()

        console.warn(S)


      }

    }
  }
}